package me.zhengjie.wcs;

import cn.hutool.core.util.ObjectUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.annotation.Log;
import me.zhengjie.modbusTCP.EntranceTCP;
import me.zhengjie.ppService.*;
import me.zhengjie.pojo.InBoundInfo;
import me.zhengjie.pojo.Request;
import me.zhengjie.pojo.Response;
import me.zhengjie.pojo.sqlServer.*;
import me.zhengjie.repository.*;
import me.zhengjie.service.PPInboundMissionService;
import me.zhengjie.service.PPOutboundOrderService;
import me.zhengjie.service.PPStorageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@RestController
@RequiredArgsConstructor
@Api(tags = "WCS上报信息")
@RequestMapping("/api/wcsReport")
public class PPWcsReport {

    private final PPDeviceStatusRepository ppDeviceStatusRepository;
    private final PPTaskResultRepository ppTaskResultRepository;
    private final PPInboundMissionHistoryRepository ppInBoundMissionHistoryRepository;
    private final PPOutboundMissionHistoryRepository ppOutBoundMissionHistoryRepository;
    private final PPStorageService ppStorageService;
    private final ObjectMapper objectMapper;
    private final PpPalletRepository ppPalletRepository;
    private final PPTaskResultService ppTaskResultService;
    private final PPInventoryService ppInventoryService;
    private final PPInfoRepository ppInfoRepository;
    private final PPMoveMissionRepository ppMoveMissionRepository;
    private final PPInventoryRepository ppInventoryRepository;
    private final PPStationService ppStationService;
    private final EntranceTCP entranceTCP;
    private final PPStationRepository ppStationRepository;
    private final PPWmsTaskRepository ppWmsTaskRepository;
    private final PPOutboundMissionRepository ppOutboundMissionRepository;
    private final PPInboundMissionRepository ppInboundMissionRepository;

    private static final Logger ppLog = LoggerFactory.getLogger("pp");

    @PostMapping(value = "/deviceStatus")
    @Log("码垛机状态")
    @ApiOperation("码垛机状态")
    @Transactional
    public Response getDeviceStatus(@RequestBody Request request) {
        try {
            Object object = request.getData();
            if (!ObjectUtil.isEmpty(object)) {

                /*DeviceStatus deviceStatus = (DeviceStatus)object;*/
                PPDeviceStatus deviceStatus = objectMapper.convertValue(object, PPDeviceStatus.class);
                ppLog.info("接受到设备状态数据:{}", deviceStatus);

                String code = deviceStatus.getCode();

                PPDeviceStatus oldDeviceStatus = ppDeviceStatusRepository.findOldDeviceStatus(code);
                ppLog.info("查找到的旧码垛机状态信息：{}", oldDeviceStatus);
                if (ObjectUtil.isEmpty(oldDeviceStatus)) {
                    ppDeviceStatusRepository.save(deviceStatus);
                    /*ppDeviceStatusRepository.saveNewStatus(deviceStatus.getCode(),deviceStatus.getEquipmentType(),deviceStatus.getAisle(),deviceStatus.getLayer(),deviceStatus.getStatus());*/
                } else {
                    ppDeviceStatusRepository.updateDeviceStatus(deviceStatus.getAisle(), deviceStatus.getLayer(), deviceStatus.getStatus(), deviceStatus.getLastUpdated(), code);
                }
                return new Response(request.getMessageId(), 1, "");
            } else {
                return new Response(request.getMessageId(), 0, "获取码垛机状态失败");
            }
        } catch (Exception e) {
            ppLog.error("码垛机状态获取失败，失败原因：{}", e.toString());
            return new Response(request.getMessageId(), 0, "获取码垛机状态失败");
        }


    }


    /**
     * 接收当前的任务状态，记录历史出入库任务
     *
     * @param request 请求体
     * @return Response 响应体
     */
    @PostMapping(value = "/taskResult")
    @Log("任务状态")
    @ApiOperation("任务状态")
    @Transactional
    public Response getTaskResult(@RequestBody Request request) {
        try {
            Object object = request.getData();
            if (!ObjectUtil.isEmpty(object)) {
                PPTaskResult data = objectMapper.convertValue(object, PPTaskResult.class);
                ppLog.info("接收到码垛机发来的任务状态信息：{}", data);
                String wmsTaskId = data.getWmsTaskId();
                PPTaskResult taskResult = ppTaskResultRepository.findPPTaskResultByWmsTaskId(wmsTaskId);
                if (ObjectUtil.isEmpty(taskResult)) {
                    // 获取失败
                    return new Response(request.getMessageId(), 0, "获取任务状态失败");
                } else {
                    doTaskResult(data);
                }

                return new Response(request.getMessageId(), 1, "");

            } else {
                // 获取失败
                ppLog.info("接收wcs任务状态异常");
                return new Response(request.getMessageId(), 0, "获取任务状态失败");
            }
        } catch (Exception e) {
            ppLog.error("接收wcs任务状态异常，异常原因：{}", e.getMessage(),e);
            // 获取失败
            return new Response(request.getMessageId(), 0, "获取任务状态失败");
        }
    }




    public void doTaskResult(PPTaskResult data) {
        ppLog.info("查询到的该条任务之前的状态：{}", data);
        String wmsTaskId = data.getWmsTaskId();
        PPTaskResult taskResult = ppTaskResultRepository.findPPTaskResultByWmsTaskId(wmsTaskId);
        ppTaskResultRepository.updateTaskResult(data.getFromLocation(), data.getToLocation(), data.getStatus(), data.getLastUpdated(), wmsTaskId);
        // 判断任务类型，保存出库入库的完成时间

        Integer taskType = data.getWcsTaskType();
        // 入库任务
        if (taskType == 1) {
            //Status,0-初始 1-取货完成 2-任务完成（放货完成）3-异常
            //取货完成释放站点
            if (data.getStatus() == 1) {
                ppStationService.refeaseStation(data.getFromLocation());
                ppLog.info("堆垛机取货成功,释放工作站：{}", data);
            }

            if (data.getStatus() == 2) {

//                //先看有没有到对应站点的出库任务
//                PPTaskResult outPPTaskResult = ppTaskResultRepository.findPPTaskResultByDetination(data.getFromLocation());
//                List<PPOutboundMission> ppOutboundMissions = ppOutboundMissionRepository.findPPOutboundMissionsByDestination(data.getLpnCode());
//
//                PPStation ppStation =  ppStationService.getStationByCode(data.getLpnCode());
                PPTaskResult ppTaskResult =  ppTaskResultRepository.findPPTaskResultByWmsTaskId(data.getWmsTaskId());
                if (ppTaskResult.getStatus()==1) {
                    //释放对应的站点
                    ppStationService.refeaseStation(data.getFromLocation());
                    ppLog.info("堆垛机未发送取货完成任务,需要再次释放工作站：{}", data);
                }

                ppLog.info("收到入库任务反馈，开始更新历史任务，储位，以及库存");
                // 任务结束记录
                int ppInboundMissionHistoryResult = ppInBoundMissionHistoryRepository.updateFinishTime(LocalDateTime.now(), taskResult.getWmsTaskId(), "任务完成");
                ppLog.info("更新的历史入库任务条数：{}", ppInboundMissionHistoryResult);
                //释放储位
                String storageCode = taskResult.getToLocation();
                int storageResult = ppStorageService.openStorage(storageCode);
                ppLog.info("更新的储位条数：{}", storageResult);

                //入库信息补全
                String palletCode = taskResult.getLpnCode();
                PpPallet ppPallet = ppPalletRepository.findByPalletCode(palletCode);
                ppLog.info("载盘已进入库区，当前载盘：{}", ppPallet);

                //先判断载盘有没有绑定pp
                if (ppPallet.getPpBatch() == null || ppPallet.getPpBatch().trim().isEmpty()) {
                    ppLog.info("该载盘没有绑定pp，是空载盘入库");
                    //空载盘入库，不需要记录库存信息
                    // 更新储位的信息
                    ppStorageService.finishInBoundNullPallet(ppPallet.getPalletCode(), storageCode);

                } else {

                    //入库存
                    InBoundInfo inBoundInfo = new InBoundInfo();
                    inBoundInfo.setPalletCode(palletCode);
                    // inBoundInfo.setPpInfo(ppInfoRepository.getPPInfoByPpBatch(ppPallet.getPpBatch()));
                    PPInfo ppInfo = ppInfoRepository.getPPInfoByPpBatch(ppPallet.getPpBatch());
                    inBoundInfo.setStationCode(taskResult.getFromLocation());
                    inBoundInfo.setIsPackage(ppInfo.getIsPakage());
                    ppInventoryService.savePPInventory(inBoundInfo, ppInfo, storageCode);

                    // 更新储位的信息
                    ppStorageService.finishInBound(ppPallet.getPalletCode(), storageCode);

                }

                ppTaskResultService.deleteByWmsTaskId(taskResult.getWmsTaskId());

                ppWmsTaskRepository.deleteByWmsTaskId(taskResult.getWmsTaskId());

                ppLog.info("删除任务结果表中的任务：{},入库任务完成", taskResult);


            }
            // 出库任务
            //Status,0-初始 1-取货完成 2-任务完成（放货完成）3-异常
        } else if (taskType == 2) {
            PPStation ppStation = ppStationRepository.findByStationCode(taskResult.getToLocation());
            if (data.getStatus() == 1) {
                // 更新taskResult
                //todo 切换工作站的模式
                entranceTCP.write(ppStation.getAddress(), 2, 5);
                ppLog.info("收到出库任务反馈,切换工作站的模式为出库");
                //输出到控制台
                log.info("收到出库任务反馈,切换工作站的模式为出库");
            }
            if (data.getStatus() == 2) {

                 PPTaskResult ppTaskResult =  ppTaskResultRepository.findPPTaskResultByWmsTaskId(data.getWmsTaskId());
                 if (ppTaskResult.getStatus()==1) {
                     //todo 切换工作站的模式
                     entranceTCP.write(ppStation.getAddress(), 2, 5);
                 }

                //先看有没有到对应站点的入库任务
                ppLog.info("收到出库任务{}反馈，开始更新历史任务，储位，以及库存", data.getWmsTaskId());
                //如果工作站类型是1就释放工作站
                if (ppStation.getStationType() == 1) {
                    ppStationRepository.refeaseStation(ppStation.getStationCode());
                }

                PpPallet ppPallet = ppPalletRepository.findByPalletCode(taskResult.getLpnCode());
                //查询出库单
                String missionCode = taskResult.getWmsTaskId();

                //先判断是不是空载盘出库
                if (ppPallet.getPpBatch() == null || ppPallet.getPpBatch().trim().isEmpty()) {

                    // 任务结束记录
                    ppOutBoundMissionHistoryRepository.updateFinishTime(LocalDateTime.now(), taskResult.getWmsTaskId(), "任务完成");

                    // 释放储位
                    ppStorageService.cleanStorage(taskResult.getFromLocation());


                    ppTaskResultService.deleteByWmsTaskId(taskResult.getWmsTaskId());

                    ppWmsTaskRepository.deleteByWmsTaskId(taskResult.getWmsTaskId());
                } else {

                                /*Integer orderId = ppOutBoundMissionRepository.findPPOutboundMissionByMissionCode(missionCode).getOutBoundOrderId();
                                List<PPOutboundMission> outBoundMissions = ppOutBoundMissionRepository.findPPOutboundMissionsByOutBoundOrderId(orderId);*/

//                                if (outBoundMissions.isEmpty()) {
//                                    ppLog.info("出库单：{}{}", orderId, "结束！");
//                                    ppOutBoundOrderService.finishOrder(orderId);
//                                }

                    // 任务结束记录
                    ppOutBoundMissionHistoryRepository.updateFinishTime(LocalDateTime.now(), taskResult.getWmsTaskId(), "任务完成");
                    // 释放储位
                    ppStorageService.cleanStorage(taskResult.getFromLocation());


                    //更新库存状态
                    String palletCode = ppPallet.getPalletCode();
                    ppInventoryService.outBoundByPalletCode(palletCode);


                                /*// 删除任务，任务状态。
                                ppOutBoundMissionRepository.deletePPOutboundMissionByMissionCode(missionCode);*/
                    ppTaskResultService.deleteByWmsTaskId(taskResult.getWmsTaskId());

                    ppWmsTaskRepository.deleteByWmsTaskId(taskResult.getWmsTaskId());

                    //解绑载盘，如果工作站类型是1就要把载盘也给删除
                    if (ppStation.getStationType() == 1) {
                        ppPalletRepository.deleteByPalletCode(palletCode);
                    }/*else {
                                    ppPalletService.unBindPallet(palletCode);
                                }*/

                }
            }

            ppLog.info("删除任务结果表中的任务：{},出库任务完成", taskResult);
            //移库任务
        } else if (taskType == 3) {
            //Status,0-初始 1-取货完成 2-任务完成（放货完成）3-异常
            if (data.getStatus() == 2) {
                ppLog.info("收到移库任务反馈，开始更新历史任务，储位，以及库存");

                //释放储位
                ppStorageService.cleanStorage(taskResult.getFromLocation());

                //更改库存位置信息
                PPInventory ppInventory = ppInventoryRepository.findPPInventoryByStorageCode(taskResult.getFromLocation());
                ppInventory.setStorageCode(taskResult.getToLocation());
                //取消库存禁用
                ppInventory.setLockStatus(1);
                ppInventoryRepository.save(ppInventory);
                ppLog.info("移库完成，当前库存信息：{}", ppInventory);

                // 更新储位的信息
                ppStorageService.finishInBound(taskResult.getLpnCode(), taskResult.getToLocation());
                ppTaskResultService.deleteByWmsTaskId(taskResult.getWmsTaskId());

                //移库任务完成后，取消禁用储位
                int storageResult = ppStorageService.openStorage(taskResult.getToLocation());
                ppLog.info("更新的储位条数：{}", storageResult);

                //删除移库任务
                ppMoveMissionRepository.deletePPMoveMissionByMissionCode(taskResult.getWmsTaskId());


                // 任务结束记录
                int ppMoveMissionHistoryResult = ppMoveMissionRepository.updateFinishTime(LocalDateTime.now(), taskResult.getWmsTaskId(), "任务完成");
                ppLog.info("更新的历史移库任务条数：{}", ppMoveMissionHistoryResult);


            }

            ppLog.info("删除任务结果表中的任务：{},移库任务完成", taskResult);
        }


    }

}
